/**
 * Copyright (c) 2008, Fabien Antoine
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

package fas.massload.file;

import fas.massload.events.MassLoaderEvent;
import fas.massload.events.MassLoaderErrorEvent;
import fas.massload.file.ILoadFile;

import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.Event;
import flash.events.ProgressEvent;

import flash.net.URLRequest;

import flash.media.Sound;
import flash.media.SoundLoaderContext;

class SLoadFile extends EventDispatcher, implements ILoadFile
{		
	//---------//
	//Variables//
	//---------//
	
	private var uRequest:URLRequest;
	private var sLoader:Sound;
	
	
	// ----------- //
	// Constructor //
	// ----------- //
	
	/**
	 * Constructor of ULoadFile
	 * @param		urlRequest		URLRequest		URLRequest of the file to download
	 */
	public function new( urlRequest:URLRequest, sName:String )
	{
		super();
		
		// Save the properties
		uRequest = urlRequest;
		
		name 		= sName;
		type		= FileType.SoundLoader;
		loading 	= false;
	}
	
	
	
	// -------------- //
	// Public methods //
	// -------------- //
	
	/**
	 * Start the loading of the file
	 */
	public function load():Void
	{
		if( !loading )
		{
			loading = true;
			
			// Initialise the loader
			sLoader = new Sound();
			
			// Adds events
			registerEvents();
			
			// Launch the loading
			sLoader.load( uRequest, new SoundLoaderContext(false) );
		}
	}
	
	/**
	 * Stop the loading of the file
	 */
	public function close( ?error:Bool=false ):Void
	{
		if ( loading )
		{
			loading = false;
			
			try
			{
				// Stop the loading
				sLoader.close();
			}catch( e:Dynamic ){}
			
			// removes events
			unRegisterEvents();
			
			// Dispatch close event
			if( error ) dispatchEvent( new MassLoaderEvent( MassLoaderEvent.CLOSE, this ) );
		}
	}
	
	/**
	 * String version of the LoadFile
	 * @return				String			String version of the LoadFile		
	 */
	public override function toString():String
	{
		return "<SLoadFile>" + name + "[" + uRequest.url + "]";
	}
	
	
	// --------------- //
	// Private methods //
	// --------------- //
	
	/**
	 * Adds all events listeners for the Loader
	 */
	private function registerEvents():Void
	{
		// Adds events listener
		sLoader.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
		sLoader.addEventListener( Event.COMPLETE, onComplete );
		sLoader.addEventListener( ProgressEvent.PROGRESS, onProgress );
		sLoader.addEventListener( Event.OPEN, onOpen );
	}
	
	/**
	 * Removes all events listeners for the Loader
	 */
	private function unRegisterEvents():Void
	{
		// Removes events listener
		sLoader.removeEventListener( IOErrorEvent.IO_ERROR, onIOError );
		sLoader.removeEventListener( Event.COMPLETE, onComplete );
		sLoader.removeEventListener( ProgressEvent.PROGRESS, onProgress );
		sLoader.removeEventListener( Event.OPEN, onOpen );
	}
	
	
	// ------ //
	// Events //
	// ------ //
	
	/**
	 * Event called when io error
	 * @param	ev			IOErrorEvent		Event received
	 */
	private function onIOError( ev:IOErrorEvent ):Void
	{
		// Close the loader
		close( true );
		
		// Dispatch error events
		dispatchEvent( new MassLoaderErrorEvent( MassLoaderErrorEvent.IO_ERROR, this, ev.text ) );
		dispatchEvent( new MassLoaderErrorEvent( MassLoaderErrorEvent.ERROR, this, ev.text ) );
	}
	
	/**
	 * Event called when complete loading
	 * @param	ev			Event				Event received
	 */
	private function onComplete( ev:Event ):Void
	{
		// Dispatch the event
		dispatchEvent( new MassLoaderEvent( MassLoaderEvent.COMPLETE, this ) );
		
		// Close the loader
		close();
	}
	
	/**
	 * Event called when progress loading
	 * @param	ev			ProgressEvent		Event received
	 */
	private function onProgress( ev:ProgressEvent ):Void
	{
		// Dispatch the event
		dispatchEvent( new MassLoaderEvent( MassLoaderEvent.PROGRESS, this, ev.bytesLoaded, ev.bytesTotal ) );
	}
	
	/**
	 * Event called when download begin
	 * @param	ev			Event				Event received
	 */
	private function onOpen( ev:Event ):Void
	{
		// Dispatch the event
		dispatchEvent( new MassLoaderEvent( MassLoaderEvent.OPEN, this ) );
	}
	
	
	
	// --------- //
	// Accessors //
	// --------- //
	
	/**
	 * State of loading
	 */
	public var loading( default, null ):Bool;
	
	/**
	 * Type of the LoadFile: SoundLoader
	 */
	public var type( default, null ):FileType;
	
	/**
	 * Name of the LoadFile
	 */
	public var name( default, default ):String;
	
	/**
	 * Number of bytes loaded for the LoadFile
	 */
	public var bytesLoaded( getBytesLoaded, null ):UInt;
	private function getBytesLoaded():UInt { return sLoader.bytesLoaded; }
	
	
	/**
	 * Total number of bytes of the LoadFile
	 */
	public var bytesTotal( getBytesTotal, null ):UInt;
	private function getBytesTotal():UInt { return sLoader.bytesTotal; }
	
	/**
	 * Data received from the file
	 */
	public var content( getContent, null ):Dynamic;
	private function getContent():Dynamic { return sLoader; }
}